﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System.Numerics;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Loop;
using TrackSystem.Entities.Dtos.Slave;
using TrackSystem.Entities.Extensions;
using TrackSystem.Entities.Models;
using TrackSystem.Entities.RequestFeatures;
using TrackSystem.EntityFramework.Repositories.Extensions;

namespace TrackSystem.EntityFramework.Repositories;

public class SlaveRepository: Repositories<SlaveTable, int>, ISlaveRepository
{
    private readonly IMapper _mapper;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="dbContent"></param>
    /// <param name="mapper"></param>
    public SlaveRepository(TkDBContent dbContent, IMapper mapper) : base(dbContent)
    {
        this._mapper = mapper;
    }
 
    public PagedList<SlaveTable> GetPagedSlaves(RequestParameter parameter)
    {
        return Table.OrderByQuery(parameter.QueryString)
            .ToPagedList(parameter.PageNumber, parameter.PageSize); 
    }

    public async Task<ApiResult<SlaveDto>> GetSingleSlaveAsync(int id)
    {
        var count = await Table.CountAsync(a => a.Id == id);
        if (count == 0)
        {
            return ApiResult<SlaveDto>.Fail($"从站服务器不存在");
        }
        var entity = await Table.SingleOrDefaultAsync(a => a.Id == id);
        return ApiResult<SlaveDto>.Ok(_mapper.Map<SlaveDto>(entity));
    }

    /// <summary>
    /// 添加从站信息
    /// </summary>
    /// <param name="slave"></param>
    /// <returns></returns>
    public async Task<ApiResult<SlaveTable>> AddSlaveAsync(SlaveDto slave)
    {
        try
        {
            // 检查是否存在同名的服务器
            var counter = await CountAsync(a => a.Name == slave.Name);
            if (counter > 0)
            {
                return ApiResult<SlaveTable>.Fail($"存在同名的从站(Name: {slave.Name})");
            }
            
            // 检查端口号是否重复
            if (slave.PortCategory != PortCategory.SRIAL)
            {
                counter = await CountAsync(a => a.PortCategory != PortCategory.SRIAL
                                                && a.LocalIP == slave.LocalIP
                                                && a.LocalPort == slave.LocalPort);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.LocalIP}:{slave.LocalPort})");

                counter = await _dbContext.Channels.CountAsync(a => a.PortCategory != PortCategory.SRIAL
                                                                 && a.localIp == slave.LocalIP
                                                                 && a.localPort == slave.LocalPort);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.LocalIP}:{slave.LocalPort})");

                if (slave.PortCategory == PortCategory.UDP)
                {
                    counter = await CountAsync(a => a.PortCategory == PortCategory.UDP
                                                    && a.RemoteIP == slave.RemoteIP
                                                    && a.RemotePort == slave.RemotePort);
                    if (counter > 0)
                        return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.RemoteIP}:{slave.RemoteIP})");

                    counter = await _dbContext.Channels.CountAsync(a => a.PortCategory == PortCategory.UDP
                                                                        && a.Ip == slave.RemoteIP
                                                                        && a.Port == slave.RemotePort);
                    if (counter > 0)
                        return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.RemoteIP}:{slave.RemotePort})");
                }
            }
            else
            {
                counter = await CountAsync(a => a.PortCategory == PortCategory.SRIAL
                                                && a.Comx == slave.Comx);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.Comx})");
                
                counter = await _dbContext.Channels.CountAsync(a => a.PortCategory == PortCategory.SRIAL &&
                                                                    a.COMn != null &&
                                                                    a.COMn.Trim() == slave.Comx.Trim());
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.Comx})");
            }
            
            // 检查只读存储器变量表中的变量是否存在或者正确
            
            
            // 检查读写寄存器中的变量表是否存在或者正确
            
            
            var entity = await InsertAsync(_mapper.Map<SlaveTable>(slave));
            
            
            return ApiResult<SlaveTable>.Ok(entity);
        }
        catch (Exception ex)
        {
            return ApiResult<SlaveTable>.Fail($"添加从站信息错误(Name: {slave.Name}): {ex.Message}");
        }
    }

    /// <summary>
    /// 更新从站信息
    /// </summary>
    /// <param name="slave"></param>
    /// <returns></returns>
    public async Task<ApiResult<SlaveTable>> UpdateSlaveAsync(SlaveDto slave)
    {
        try
        {
            var counter = await CountAsync(a => a.Name == slave.Name && a.Id != slave.Id);
            if (counter > 0)
            {
                return ApiResult<SlaveTable>.Fail($"存在同名的从站(Name: {slave.Name})");
            }
            
            if (slave.PortCategory != PortCategory.SRIAL)
            {
                counter = await CountAsync(a => a.PortCategory != PortCategory.SRIAL
                                                && a.Id != slave.Id
                                                && a.LocalIP == slave.LocalIP
                                                && a.LocalPort == slave.LocalPort);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.LocalIP}:{slave.LocalPort})");

                counter = await _dbContext.Channels.CountAsync(a => a.PortCategory != PortCategory.SRIAL
                                                                 && a.localIp == slave.LocalIP
                                                                 && a.localPort == slave.LocalPort);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.LocalIP}:{slave.LocalPort})");

                if (slave.PortCategory == PortCategory.UDP)
                {
                    counter = await CountAsync(a => a.PortCategory == PortCategory.UDP
                                                    && a.Id != slave.Id
                                                    && a.RemoteIP == slave.RemoteIP
                                                    && a.RemotePort == slave.RemotePort);
                    if (counter > 0)
                        return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.RemoteIP}:{slave.RemoteIP})");

                    counter = await _dbContext.Channels.CountAsync(a => a.PortCategory == PortCategory.UDP
                                                                        && a.Ip == slave.RemoteIP
                                                                        && a.Port == slave.RemotePort);
                    if (counter > 0)
                        return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.RemoteIP}:{slave.RemotePort})");
                }
            }
            else
            {
                counter = await CountAsync(a => a.PortCategory == PortCategory.SRIAL
                                                && a.Id != slave.Id
                                                && a.Comx == slave.Comx);
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.Comx})");
                
                counter = await _dbContext.Channels.CountAsync(a => a.PortCategory == PortCategory.SRIAL &&
                                                                    a.COMn != null &&
                                                                    a.COMn.Trim() == slave.Comx.Trim());
                if (counter > 0)
                    return ApiResult<SlaveTable>.Fail($"该通信端口已被占用({slave.Comx})");
            }

            

            var entity = _mapper.Map<SlaveTable>(slave);

            await UpdateAsync(entity);

            return ApiResult<SlaveTable>.Ok(entity);
        }
        catch (Exception ex)
        {
            return ApiResult<SlaveTable>.Fail($"更新从站信息错误(Name: {slave.Name}): {ex.Message}");
        }
    }

    public Task<ApiResult<SlaveDto>> DeleteSlaveAsync(int Id)
    {
        throw new NotImplementedException();
    }
}